package com.swak.benchmark;

import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import com.swak.asm.Wrapper;
import com.swak.proxy.HelloService;
import com.swak.proxy.HelloServiceImpl;
import com.swak.proxy.cglib.CglibProxy;
import com.swak.proxy.jdk.JdkProxy;
import com.swak.proxy.mock.MockCglibHelloService;

/**
 * 使用纯编译模式： -Xmixed
 * Benchmark                    Mode  Cnt           Score   Error  Units
 * ProxyPerformance.CGLIB      thrpt       1177219974.569          ops/s
 * ProxyPerformance.JAVASSIST  thrpt       5134583500.474          ops/s
 * ProxyPerformance.JDK        thrpt       1345513461.398          ops/s
 * ProxyPerformance.MockCGLIB  thrpt       4089528327.562          ops/s
 * ProxyPerformance.NATIVE     thrpt       6372070443.876          ops/s
 * 
 * 使用纯编译模式： -Xcomp
 * Benchmark                    Mode  Cnt           Score   Error  Units
 * ProxyPerformance.CGLIB      thrpt        609009541.185          ops/s
 * ProxyPerformance.JAVASSIST  thrpt       1862697113.444          ops/s
 * ProxyPerformance.JDK        thrpt        332843213.324          ops/s
 * ProxyPerformance.MockCGLIB  thrpt       4069674500.285          ops/s
 * ProxyPerformance.NATIVE     thrpt       2332677475.217          ops/s
 * 
 * @author 618lf
 */
@Warmup(iterations = 2) // 预热的迭代次数
@OutputTimeUnit(TimeUnit.SECONDS)
@Measurement(iterations = 1, time = -1, timeUnit = TimeUnit.SECONDS, batchSize = -1)
@Threads(4)
@Fork(1)
public class ProxyPerformance {

	@State(Scope.Benchmark)
	public static class BenchmarkState {
		HelloService service = new HelloServiceImpl();
		JdkProxy jdkProxy = new JdkProxy(HelloService.class, service);
		CglibProxy cglibProxy = new CglibProxy(service);
		HelloService jdkProxyHelloService = (HelloService) jdkProxy.getProxy();
		HelloService cglibProxyHelloService = (HelloService) cglibProxy.getProxy();
		Wrapper wrapper = Wrapper.getWrapper(HelloService.class);
		MockCglibHelloService mockCglibHelloService = new MockCglibHelloService(service);
	}

	@Benchmark
	public void NATIVE(BenchmarkState state) {
		state.service.say();
	}

	@Benchmark
	public void JAVASSIST(BenchmarkState state) throws NoSuchMethodException, InvocationTargetException {
		state.wrapper.invokeMethod(state.service, "say(void)", null);
	}

	@Benchmark
	public void JDK(BenchmarkState state) {
		state.jdkProxyHelloService.say();
	}

	@Benchmark
	public void MockCGLIB(BenchmarkState state) {
		state.mockCglibHelloService.say();
	}

	@Benchmark
	public void CGLIB(BenchmarkState state) {
		state.cglibProxyHelloService.say();
	}

	public static void main(String[] args) throws RunnerException {
		Options opt = new OptionsBuilder().include(ProxyPerformance.class.getSimpleName()).forks(1).build();
		new Runner(opt).run();
	}
}
